package com.priox.sigar.ws;

import com.mm.support.mapper.DTOMapperService;
import com.priox.sigar.application.checkpoint.RegistroCheckPointApp;
import com.priox.sigar.client.dto.CheckPointDTO;
import com.priox.sigar.client.dto.CuentaContableDTO;
import com.priox.sigar.domain.model.CheckPoint;
import com.priox.sigar.domain.model.constantes.PathConstant;
import com.priox.sigar.enums.ProcesoEstado;
import com.priox.sigar.enums.TipoCuenta;
import com.priox.sigar.server.infrastructure.persistence.exception.ApplicationException;
import com.priox.sigar.server.infrastructure.persistence.util.ApplicationProperties;
import com.priox.sigar.util.FileUtil;
import com.priox.sigar.util.TimeObserver;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.event.FileUploadEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.event.ActionEvent;
import javax.jws.WebService;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

@WebService(endpointInterface = "com.priox.sigar.ws.GenericInvoker")
public class GenericInvokerImpl implements GenericInvoker {

    private static final Logger LOG = LoggerFactory.getLogger(GenericInvokerImpl.class);
    private static final Logger LOGGER = LoggerFactory.getLogger("checkpointLog");

    @Autowired
    protected JobLauncher jobLauncher;

    @Autowired
    protected RegistroCheckPointApp registroCheckPointApp;

    @Autowired
    @Qualifier("jobCuentaPorPagar")
    private Job jobCuentaPorPagar;

    @Autowired
    DTOMapperService mapperService;

    static AtomicLong workerId = new AtomicLong();

    @PostConstruct
    public void init() {
        PathConstant.DIR_ROOT = ApplicationProperties.getDirectorio();
        PathConstant.DIR_TMP = PathConstant.DIR_ROOT + "\\tmp";
        PathConstant.DIR_JASPER= PathConstant.DIR_ROOT + "\\jasper";
    }
    public String invoke() {
        CheckPointDTO nuevoCheckPoint = new CheckPointDTO();
        onFileUpload(nuevoCheckPoint);
        Long checkPointId=cargarInformacion(nuevoCheckPoint);
        validarInformacion(checkPointId,nuevoCheckPoint);
        return "OK";
    }

    public void onFileUpload(CheckPointDTO nuevoCheckPoint) {
        long checkPointId= workerId.incrementAndGet();
        SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy-kkmmss");
        String newFileName = "C1_" + sdf.format(new Date()) + "_" + workerId.incrementAndGet() + ".csv";
        nuevoCheckPoint.getArchivos().add(newFileName);
        nuevoCheckPoint.setNombreArchivo(newFileName);
        nuevoCheckPoint.setFechaCorte(new Date());

        File file = new File("D:\\sigar_files\\tmp\\base.csv");

        try {
            FileUtil.copyFile(file.getName(), new FileInputStream(file), nuevoCheckPoint.getNombreArchivo());
        } catch (IOException e) {
            e.printStackTrace();
            throw new ApplicationException("Error al copiar el archivo ");
        }
    }


    public Long cargarInformacion(CheckPointDTO nuevoCheckPoint) {

        if (StringUtils.isBlank(nuevoCheckPoint.getNombreArchivo()) || nuevoCheckPoint.getArchivos().isEmpty()) {
            throw new ApplicationException("El archivo no a sido cargado");
        }
        nuevoCheckPoint.setUsuarioId(999l);
        nuevoCheckPoint.setEstado(ProcesoEstado.BORRADOR);
        nuevoCheckPoint.setTipo(TipoCuenta.CUENTA_X_PAGAR);
        CheckPoint checkPoint = mapperService.map(nuevoCheckPoint, CheckPoint.class);
        checkPoint.setComentario("TEST");
        checkPoint.setFechaCorte(new Date());
        registroCheckPointApp.save(checkPoint, false);
        nuevoCheckPoint.setCheckPointId(checkPoint.getCheckPointId());
        LOG.info("CheckPoint creado <" + nuevoCheckPoint.getCheckPointId() + ">");
        return checkPoint.getCheckPointId();

    }

    public void validarInformacion(Long checkPointId,CheckPointDTO nuevoCheckPoint) {
        List<String> archivos = nuevoCheckPoint.getArchivos();
        TimeObserver tiempo=new TimeObserver("Proceso de archivo ");
        tiempo.empezar();
        int i = 1;
        for (String archivo : archivos) {
            LOG.info("enviando a procesar el archivo  <" + archivo + ">");
            validarInformacionIntern(checkPointId,nuevoCheckPoint.getFechaCorte(), archivo, i == archivos.size());
            i++;
        }
        tiempo.terminar();
        LOGGER.info(tiempo.mostrarMsg());
    }


    public String validarInformacionIntern(Long checkPointId,Date fechaCorte, String nombreArchivo, boolean ultimo) {
        String archivo = PathConstant.DIR_TMP + File.separator + nombreArchivo;

        JobParametersBuilder jpBuilder = new JobParametersBuilder()
                .addString("input.file.name", archivo)
                .addLong("input.usuarioId", 999l)
                .addLong("input.checkPointId", checkPointId)
                .addDate("input.fechaCorte", fechaCorte);
        JobExecution execution = null;
        try {
            execution = jobLauncher.run(jobCuentaPorPagar, jpBuilder.toJobParameters());
            if (ExitStatus.COMPLETED.equals(execution.getExitStatus())) {
                registroCheckPointApp.finalizar(checkPointId);
                return "1";
            } else {
                throw new ApplicationException("Error al procesar la tarea IN MAPPER");
            }
        } catch (ApplicationException e) {
            e.printStackTrace();
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ApplicationException("Error al procesar la tarea");
        }
    }
}
